//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Resource Application Block
//===============================================================================

using System;
using System.Globalization;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Windows.Forms;

namespace EntLibContrib.Resource.Configuration.Design.Editors
{
  /// <summary>
  /// <para>Represents the UI for the assembly selector dialog.</para>
  /// </summary>
  public partial class ResourceSelectorUI : Form
  {
		#region Constants
    private const string AssemblyFileFilter = "Assemblies (*.exe;*.dll) | *.exe;*.dll";
    #endregion

		#region Fields
		private OpenFileDialog openFileDialog = new OpenFileDialog();
    private ResourceSelector selector;
		#endregion

		#region Properties
		/// <summary>
		/// Gets the <see cref="AssemblyResourceName"/> selected for use.
		/// </summary>
		/// <value>The <see cref="AssemblyResourceName"/> selected for use.</value>
		public AssemblyResourceName SelectedResource
		{
			get { return this.treeView.SelectedNode.Tag as AssemblyResourceName; }
		}

		/// <summary>
		/// Gets the <see cref="ImageList"/> for the types.
		/// </summary>
		/// <value>The <see cref="ImageList"/> for the types.</value>
		internal ImageList ResourceImageList
		{
			get { return this.resourceImageList; }
		}
		#endregion

		#region Construction
		/// <summary>
		/// Initialize a new instance of the <see cref="ResourceSelectorUI"/> class.
		/// </summary>
    public ResourceSelectorUI()
    {
      InitializeComponent();
      openFileDialog.Filter = AssemblyFileFilter;
    }

		/// <summary>
		/// Initialize a new instance of the <see cref="ResourceSelectorUI"/> class.
		/// </summary>
		/// <param name="currentAssemblyResourceName">Name of the current assembly resource.</param>
		public ResourceSelectorUI(AssemblyResourceName currentAssemblyResourceName) : this()
		{
			this.openFileDialog.DereferenceLinks = false;
			this.selector = new ResourceSelector(currentAssemblyResourceName, this.treeView);
			this.treeView.Select();
		}
		#endregion

		#region Private Methods
		/// <summary>
		/// Called when [browse button click].
		/// </summary>
		/// <param name="sender">The sender.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void OnBrowseButtonClick(object sender, EventArgs e)
    {
      DialogResult result = this.openFileDialog.ShowDialog();
      if (result == DialogResult.OK)
      {
        try
        {
          Assembly assembly = Assembly.LoadFrom(GetAssemblyName(this.openFileDialog.FileName));
          if (!this.selector.LoadTreeView(assembly))
          {
            DisplayMessageBox(String.Format(CultureInfo.CurrentCulture, InternalResources.NoResourcesFoundInAssemblyErrorMessage, assembly.GetName().Name), InternalResources.NoResourcesFoundInAssemblyCaption);
          }
        }
        catch (FileNotFoundException ex)
        {
          DisplayMessageBox(String.Format(CultureInfo.CurrentCulture, InternalResources.AssemblyLoadFailedErrorMessage, ex.Message), string.Empty);
          return;
        }
        catch (BadImageFormatException ex)
        {
          DisplayMessageBox(String.Format(CultureInfo.CurrentCulture, InternalResources.AssemblyLoadFailedErrorMessage, ex.Message), string.Empty);
          return;
        }
      }
    }

		/// <summary>
		/// Called when [tree view double click].
		/// </summary>
		/// <param name="sender">The sender.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void OnTreeViewDoubleClick(object sender, EventArgs e)
    {
      if (SelectedResource != null)
      {
				this.OnOkButtonClick(this, EventArgs.Empty);
      }
    }

		/// <summary>
		/// Called when [ok button click].
		/// </summary>
		/// <param name="sender">The sender.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void OnOkButtonClick(object sender, EventArgs e)
    {
      DialogResult = DialogResult.OK;
      Close();
    }

		/// <summary>
		/// Called when [cancel button click].
		/// </summary>
		/// <param name="sender">The sender.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void OnCancelButtonClick(object sender, EventArgs e)
		{
			DialogResult = DialogResult.Cancel;
			Close();
		}

		/// <summary>
		/// Gets the name of the assembly.
		/// </summary>
		/// <param name="fileName">Name of the file.</param>
		/// <returns>An assembly file name</returns>
		private string GetAssemblyName(string fileName)
		{
			string assemblyFilename = fileName;
			try
			{
				string tempFilename = Path.GetTempFileName();
				File.Copy(this.openFileDialog.FileName, tempFilename, true);
				assemblyFilename = tempFilename;
			}
			catch (IOException)
			{
				// If we cant copy the file to temp directory.
				// We will use the original assembly file instead. The downside
				// of using the original assembly file is that you cannot 
				// update the assembly containing the type
				// until you close the Configuration Manager tool.
			}
			return assemblyFilename;
		}

		/// <summary>
		/// Displays the message box.
		/// </summary>
		/// <param name="message">The message.</param>
		/// <param name="caption">The caption.</param>
		private void DisplayMessageBox(string message, string caption)
		{
			DisplayMessageBox(message, caption, MessageBoxIcon.Information);
		}

		/// <summary>
		/// Displays the message box.
		/// </summary>
		/// <param name="message">The message.</param>
		/// <param name="caption">The caption.</param>
		/// <param name="icon">The icon.</param>
		private void DisplayMessageBox(string message, string caption, MessageBoxIcon icon)
		{
			MessageBoxOptions options = (MessageBoxOptions)0;

			if (RightToLeft == RightToLeft.Yes)
			{
				options = MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign;
			}

			MessageBox.Show(message, caption, MessageBoxButtons.OK, icon, MessageBoxDefaultButton.Button1, options);
		}
		#endregion
  }
}